package server

import (
	"context"
	"crypto/tls"
	"device-modbus/core"
	"device-modbus/plugin"
	"errors"
	"fmt"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// Server gRPC 服务实例
type Server struct {
	plugin.UnimplementedPluginServiceServer                // 嵌入默认实现（避免接口未全实现报错）
	cfg                                     Config         // 服务配置
	grpcServer                              *grpc.Server   // gRPC 原生服务实例
	listener                                net.Listener   // 网络监听器
	shutdownChan                            chan os.Signal // 信号监听通道（用于优雅关闭）
	//插件实例列表
	plugins map[string]core.SensorProtocol
}

// NewServer 创建 gRPC 服务实例
func NewServer(cfg Config) *Server {
	// 初始化信号通道（监听 SIGINT、SIGTERM 信号）
	shutdownChan := make(chan os.Signal, 1)
	signal.Notify(shutdownChan, syscall.SIGINT, syscall.SIGTERM)

	server := Server{
		cfg:          cfg,
		shutdownChan: shutdownChan,
		plugins:      make(map[string]core.SensorProtocol),
	}
	server.InitPlugin(context.Background())
	return &server
}

// --------------- 实现 PluginServiceServer 接口 ---------------

// Init 初始化插件：返回插件元信息（根据实际插件类型调整）
func (s *Server) Init(ctx context.Context, req *plugin.InitRequest) (*plugin.PluginMeta, error) {
	s.cfg.Log.Println("收到 Init 请求")
	// 模拟插件元信息（实际场景可从配置/数据库加载）
	return &plugin.PluginMeta{
		ProtocolName:    "文本",    // 协议唯一标识（如 modbus/mqtt）
		ProtocolVersion: "1.0.0", // 协议版本
		PluginVersion:   "2.1.0", // 插件自身版本
		Description:     "文本协议插件，支持读写文本数据",
		Author:          "your-team <your-email@example.com>",
	}, nil
}

// 初始化插件 relay_switch.NewProtocol()以及其他目录下的协议
func (s *Server) InitPlugin(ctx context.Context) {

}

// Ping 心跳检测：返回服务健康状态
func (s *Server) Ping(ctx context.Context, req *plugin.PingRequest) (*plugin.PingResponse, error) {
	s.cfg.Log.Printf("收到 Ping 请求，客户端时间戳: %d", req.ClientTimestamp)
	// 模拟健康检查（实际可检查数据库/依赖服务连接）
	healthStatus := true
	healthInfo := "服务正常，CPU使用率: 15%，内存使用率: 20%"

	return &plugin.PingResponse{
		ServerTimestamp: time.Now().UnixMilli(), // 服务端时间戳（毫秒）
		IsHealthy:       healthStatus,
		StatusInfo:      healthInfo,
	}, nil
}

// GetType 返回支持的传感器类型
func (s *Server) GetType(ctx context.Context, req *plugin.GetTypeRequest) (*plugin.GetTypeResponse, error) {
	s.cfg.Log.Println("收到 GetType 请求")
	// 实际场景可从插件配置加载支持的类型
	return &plugin.GetTypeResponse{
		Type: "文本", // 默认类型
	}, nil
}

// GetModel 返回支持的传感器模型
func (s *Server) GetModel(ctx context.Context, req *plugin.GetModelRequest) (*plugin.GetModelResponse, error) {
	s.cfg.Log.Println("收到 GetModel 请求")
	// 实际场景可从插件配置加载支持的模型
	return &plugin.GetModelResponse{
		Model:           "AHT20",                             // 默认模型
		SupportedModels: []string{"AHT20", "SHT30", "DHT11"}, // 支持的所有模型
	}, nil
}

// BuildRequest 构建协议请求数据（核心业务逻辑，根据协议自定义）
func (s *Server) BuildRequest(ctx context.Context, req *plugin.BuildRequestRequest) (*plugin.BuildRequestResponse, error) {
	s.cfg.Log.Printf("收到 BuildRequest 请求，命令: %s，参数: %v", req.Command, req.Params)

	return &plugin.BuildRequestResponse{
		Success: true,
		Data:    []byte("我是文本"),
	}, nil
}

// ParseResponse 解析协议响应数据（核心业务逻辑，根据协议自定义）
func (s *Server) ParseResponse(ctx context.Context, req *plugin.ParseResponseRequest) (*plugin.ParseResponseResponse, error) {

	return &plugin.ParseResponseResponse{
		Success: true,
		Data: &plugin.SensorData{
			Protocol:  "文本",
			Type:      "文本",
			Model:     "文本",
			Values:    map[string]string{"文本": string(req.Data)},
			Timestamp: time.Now().UnixMilli(),
			IsValid:   true,
		},
		ParseTime: time.Since(time.Now()).Microseconds(),
	}, nil
}

// --------------- 服务生命周期管理 ---------------

// Start 启动 gRPC 服务
func (s *Server) Start() error {
	// 1. 创建网络监听器
	listener, err := net.Listen("tcp", s.cfg.ListenAddr)
	if err != nil {
		return fmt.Errorf("监听地址 %s 失败: %w", s.cfg.ListenAddr, err)
	}
	s.listener = listener
	s.cfg.Log.Printf("gRPC 服务已监听: %s（TLS: %v）", s.cfg.ListenAddr, s.cfg.TLSEnabled)

	// 2. 创建 gRPC 服务实例
	s.grpcServer = grpc.NewServer(s.cfg.GetGRPCServerOpts()...)

	// 3. 注册插件服务
	plugin.RegisterPluginServiceServer(s.grpcServer, s)
	s.cfg.Log.Println("PluginService 服务已注册")

	// 4. 启动服务（非阻塞，通过 goroutine 运行）
	go func() {
		if err := s.grpcServer.Serve(s.listener); err != nil && !errors.Is(err, grpc.ErrServerStopped) {
			s.cfg.Log.Fatalf("gRPC 服务异常退出: %v", err)
		}
	}()

	// 5. 监听关闭信号（阻塞，直到收到信号）
	s.waitForShutdown()
	return nil
}

// waitForShutdown 等待关闭信号并执行优雅关闭
func (s *Server) waitForShutdown() {
	// 阻塞直到收到 SIGINT/SIGTERM 信号
	<-s.shutdownChan
	s.cfg.Log.Println("收到关闭信号，开始优雅关闭 gRPC 服务")

	// 1. 创建关闭上下文（带超时）
	shutdownCtx, cancel := context.WithTimeout(context.Background(), s.cfg.ShutdownTimeout)
	defer cancel()

	// 2. 优雅关闭 gRPC 服务
	done := make(chan struct{})
	go func() {
		s.grpcServer.GracefulStop() // 停止接收新请求，等待现有请求处理完成
		close(done)
	}()

	// 3. 等待关闭完成或超时
	select {
	case <-done:
		s.cfg.Log.Println("gRPC 服务已优雅关闭")
	case <-shutdownCtx.Done():
		s.cfg.Log.Println("gRPC 服务关闭超时，强制退出")
		s.grpcServer.Stop() // 强制关闭
	}

	// 4. 关闭监听器
	if err := s.listener.Close(); err != nil {
		s.cfg.Log.Printf("关闭监听器失败: %v", err)
	} else {
		s.cfg.Log.Println("监听器已关闭")
	}
}

// --------------- 工具函数 ---------------

// loadTLSCreds 加载 TLS 凭证（生产环境必备）
func loadTLSCreds(certPath, keyPath string) (credentials.TransportCredentials, error) {
	// 加载服务端证书和私钥
	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		return nil, fmt.Errorf("加载证书/私钥失败: %w", err)
	}

	// 配置 TLS 服务端选项
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientAuth:   tls.NoClientCert, // 无需客户端证书（根据需求调整为 RequestClientCert/RequireAndVerifyClientCert）
	}

	return credentials.NewTLS(tlsConfig), nil
}
